import numpy as np
import torch
from d2l.torch import plot
from matplotlib import pyplot as plt

x = torch.arange(-2*torch.pi, 2*torch.pi, 0.01, requires_grad=True)
y = torch.sin(x)
y.sum().backward()       # 对非标量调用backward
dx = x.grad
# print(dx == torch.cos(x))

"""
待转换类型的PyTorch Tensor变量带有梯度，直接将其转换为numpy数据将破坏计算图，
因此numpy拒绝进行数据转换，实际上这是对开发者的一种提醒。
如果自己在转换数据时不需要保留梯度信息，可以在变量转换之前添加detach()调用。
"""
x = x.detach().numpy()
y = y.detach().numpy()
plot(x, [y, dx], 'x', 'f(x)', legend=['f(x)=sin(x)', 'df(x)/dx'])

x = np.linspace(-2*torch.pi, 2*torch.pi, 9)
xs = [r'$-2\pi$', r'$-3\pi/2$', r'$-\pi$', r'$-\pi/2$', r'$0$', r'$\pi/2$', r'$\pi$', r'$3\pi/2$', r'$2\pi$']
plt.xticks(x, xs)
plt.show()